/*
 *	Thread.h is part of Flight_Chess_Portable
 *	Copyright (C) 2008  Poison
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 *	Class:			Thread
 *	Description:	
 *	Author:			Poison <hbpoison@gmail.com>
 *	Date Created:	2008-02-26
 */

#pragma once

#include <pspthreadman.h>

class Sema
{
public:
	Sema();
	Sema( const char * name, int init = 0, int max = 0 );
	~Sema();
	int create( const char * name, int init = 0, int max = 0 );
	int drop();
	int sentSignal( int signal = 1 );
	int waitSignal( int signal = 1, unsigned int * timeout = NULL );
private:
	int handler;
};

class Callback
{
public:
	Callback();
	Callback( const char * name, void * arg = NULL );
	virtual ~Callback();
	inline bool valid() { return ( handler >= 0 )? true: false; }
	inline int getId() { return handler; }
	int create( const char * name, void * arg = NULL );
	int drop();
	int notify( int arg2 );
	int cancel();
	int getCount();
	virtual int reg() { return 0; }
	SceKernelCallbackInfo info;
	int updateInfo();
	
	static int check();
protected:
	virtual int CallbackFunction( int arg1, int arg2, void * arg ) = 0;
private:
	int handler;
	typedef struct _CallbackParam {
		Callback * entry;
		void * arg;
	} CallbackParam;
	CallbackParam nCallbackParam;
	
	static int nCallbackFunction( int arg1, int arg2, void * arg );
};

class Thread
{
public:
	Thread();
	Thread( bool free_on_term, const char * name, int priority = 0x10, int stack_size = 0x1000, unsigned int attr = PSP_THREAD_ATTR_USER );
	virtual ~Thread();
	inline bool valid() { return ( handler >= 0 )? true: false; }
	inline int getId() { return handler; }
	int getStackFreeSize();
	int getExitStatus();
	int create( bool free_on_term, const char * name, int priority = 0x10, int stack_size = 0x1000, unsigned int attr = PSP_THREAD_ATTR_USER );
	int drop();
	int start( int argc, void * argp );
	int terminate();
	int terminateDelete();
	int suspend();
	int resume();
	int wakeup();
	int cancelWakeup();
	int waitEnd( unsigned int timeout );
	int waitEndCB( unsigned int timeout );
	int changePriority( int priority );
	int releaseWait();
	
	void setupSema();
	
	SceKernelThreadInfo info;
	int updateInfo();
	enum ThreadStatus {
		TS_RUN = 0x0F,
		TS_STP = 0x00,
		TS_SUP = 0xF0
	};
	int status;
	//static func
	static int exit();
	static int exitDelete();
	static int sleep();
	static int sleepCB();
	static int delay( unsigned int msec );
	static int delayCB( unsigned int msec );
	static int changeCurrentAttr( int unk, unsigned int attr );
	static int getCurrentId();
	static int getCurrentPriority();
protected:
	virtual int ThreadEntry( int argc, void * argp ) = 0;
private:
	int handler;
	Sema * sema;
	typedef struct _ThreadParam {
		Thread * entry;
		int argc;
		void * argp;
		bool fot;
	} ThreadParam;
	ThreadParam nThreadParam;
	
	static int nThreadEntry( int argc, void * argp );
};
